import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 * @author Steffen Baumann
 * 
 */
public class LayoutingMain {

	private static final int X_LOCAL = 100;
	private static final int Y_LOCAL = 200;
	private static final int WIDTH = 400;
	private static final int HEIGHT = 400;

	private static final int BUTTON_WIDTH = 100;
	private static final int BUTTON_HEIGHT = 25;

	private static final int V_GAP = 0;
	private static final int H_GAP = 5;

	private ArrayList<String> elements = new ArrayList<String>();

	private ActionAdapter adapter = new ActionAdapter();

	private JPanel panelButtons;

	/**
	 * Default Constructor called by Main-method. Creates the whole JFrame
	 */
	public LayoutingMain() {

		for (int i = 0; i < 5; i++) {
			elements.add("Drink" + i);
		}

		// Creates a simple JFrame to add a JPanel containing the Buttons
		JFrame frame = createFrame();
		// Creates the JPanel containing all JButtons, will be updated
		// dynamically
		panelButtons = createButtonPanel();
		// Creates a Panel to add and remove Buttons --> just for testing
		JPanel testBar = createTestPanel();

		//Adds the Panel with Buttons to a JScrollPane and this scrollable component to the center of the BorderLayout.
		frame.add(new JScrollPane(panelButtons), BorderLayout.CENTER);
		//Adds the Panel containing the Add and Remove-Button to the Button of the Frame
		frame.add(testBar, BorderLayout.SOUTH);

		//Packs the Layouts to the preferred sizes (maybe also Minimum-/Maximumsize)
		frame.pack();
		
		//Sets the window visible
		frame.setVisible(true);

	}

	/**
	 * Creates a simple JFrame with predefined width and height.
	 */
	private JFrame createFrame() {
		// Sets the title
		JFrame frame = new JFrame("Title");
		// Sets the size - often used for null-Layout
		frame.setSize(new Dimension(WIDTH, HEIGHT));
		// Sets the preferred size - important for pack() and Layout-Calculating
		frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));
		// Sets the operation to be done by clicking on Close (X)
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// Sets the location of the window
		frame.setLocation(X_LOCAL, Y_LOCAL);
		return frame;
	}

	/**
	 * Creates the JPanel containing the JButtons A class variable is used to
	 * ensure the usage of the {@link #updateButtonLayout()}-Method.
	 * 
	 * @return
	 */
	private JPanel createButtonPanel() {
		// Creates a new JPanel and set it to the class variable
		panelButtons = new JPanel();
		// Sets the Layout - best Layout for Top-to-Bottom-Layout in 1 column
		BoxLayout layout = new BoxLayout(panelButtons, BoxLayout.PAGE_AXIS);
		panelButtons.setLayout(layout);
	
		// Creates the Buttons and organizes the Layout of the panel
		updateButtonLayout();
	
		return panelButtons;
	}

	/**
	 * Updates the Panel containing the JButtons. Therefore all Elements are
	 * deleted at first, afterwards the panel size is recalculated. As result
	 * the JScrollPane is showed, if the panel is lager than the frame.
	 * 
	 * All buttons will be created and added to the panel. The layout is
	 * validated to ensure all buttons are visible.
	 * 
	 * TODO: Remove just one component by click on "Remove"-Button and add one
	 * by click on "Add"-Button
	 */
	private void updateButtonLayout() {
		// Removes all Components from the panel
		panelButtons.removeAll();
	
		// Sets the size of the panel - often used for null-Layout
		panelButtons.setSize(new Dimension(BUTTON_WIDTH, elements.size()
				* BUTTON_HEIGHT));
	
		// Sets the preferred size of the panel - important for pack() and
		// Layout-Calculating
		panelButtons.setPreferredSize(new Dimension(BUTTON_WIDTH, elements
				.size() * BUTTON_HEIGHT));
	
		// Iterates through the list with elements and create for each element
		// one JButton
		for (String drink : elements) {
			// Creates the button
			JButton button = createButton(drink);
			// Adds the button to the Panel
			panelButtons.add(button);
		}
		// Validates the Layout to ensure all buttons are displayed
		panelButtons.validate();
	}

	/**
	 * Creates a new JButton with the given String as Text and Name. The
	 * {@link ActionAdapter} is also added.
	 * 
	 * @param drink
	 * @return complete defined button
	 */
	private JButton createButton(String drink) {
		// Creates a new JButton with the text of "DrinkX", where X is an
		// integer from 0
		JButton button = new JButton(drink);
		// Sets the name of the component
		button.setName(drink);
		// Sets a minimum size of the Button. Predefined values are used.
		button.setMinimumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		// Sets a maximum size of the Button. Predefined values are used.
		button.setMaximumSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		// Adds the ActionAdapter to this Button
		button.addActionListener(adapter);
		// no comment necessary ...
		return button;
	}

	/**
	 * Creates the Button Bar at the Bottom of the Frame. It is used for testing
	 * the functionality of the dynamic layout.
	 * 
	 * Two Buttons with anonymous ActionListeners are used. They call the
	 * {@link #updateButtonLayout()}-method!!!
	 * 
	 * 
	 * 
	 * @return
	 */
	private JPanel createTestPanel() {
		// Creates a new Panel as Container
		JPanel panel = new JPanel();
		// ==========================ADD==========================
		// Creates the Add-Button
		JButton add = new JButton("Add");
		// adds the ActionListener
		add.addActionListener(new ActionListener() {
			/**
			 * Changes the list containing the elements. One element is added to
			 * the end of the List and updates the Panel
			 */
			@Override
			public void actionPerformed(ActionEvent e) {
				String name = "Drink" + elements.size();
				System.out.println("----------ADD: Button " + name
						+ " -----------");
				elements.add(name);
				updateButtonLayout();
			}
		});
		// Sets the size of the button - often used for null-Layouts
		add.setSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		// Sets the size of the button - important for pack() and
		// Layout-Calculating
		add.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		// ==========================REMOVE==========================
		// Creates the Remove-Button
		JButton remove = new JButton("remove");
		// adds the ActionListener
		remove.addActionListener(new ActionListener() {
			/**
			 * Changes the list containing the elements. The last element is
			 * removed from the List. Updates the Panel
			 */
			@Override
			public void actionPerformed(ActionEvent e) {
				if (!elements.isEmpty()) {
					elements.remove(elements.size() - 1);
					System.out
							.println("----------REMOVE: last Button -----------");
					updateButtonLayout();
				}
			}
		});
		// Sets the size of the button - often used for null-Layouts
		remove.setSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
		// Sets the size of the button - important for pack() and
		// Layout-Calculating
		remove.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));

		// Sets the Gridlayout with two columns and one row. Also predefined gaps are used.
		panel.setLayout(new GridLayout(1, 2, H_GAP, V_GAP));

		//Adding the two Buttons
		panel.add(add);
		panel.add(remove);

		// Sets the panel visible
		panel.setVisible(true);
		return panel;
	}

	/**
	 * Starts the program
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new LayoutingMain();
	}

	/**
	 * Adapter for ActionEvents of the dynamic Buttons. Should call the
	 * necessary information from the DB by analyzing the name of the source.
	 * 
	 * @author Steffen Baumann
	 * 
	 */
	class ActionAdapter implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() instanceof JButton) {
				JButton clickedButton = (JButton) e.getSource();
				String name = clickedButton.getName();
				System.out.println(name);
				// TODO Check the name and call required information from DB
				// TODO Use a HashMap for linking Strings(the names) to a
				// Primitive and check them. String comparison is more expensive
			}
		}
	}
}
